# -*- coding: utf-8 -*-

import json
import time

from enum import Enum


class VideoFormat(Enum):
    V_APP = "APP"
    V_HR_HDTV = "HR-HDTV"
    V_HDTV = "HDTV"
    V_WEB_DL = "WEB-DL"
    V_1080P = "1080P"
    V_720P = "720P"
    V_MP4 = "MP4"
    V_DVD = "DVD"
    V_DVDSCR = "DVDSCR"
    V_RMVB = "RMVB"
    V_IDONTCARE = "_"


class WayFormat(Enum):
    W_ED2K = "1"  # 电驴
    W_BAIDUYUN = "102"  # 百度云
    W_WEIYUN = "115"  # 微云
    W_IDONTCARE = "_"  # 任意格式都可以


Download_Way_Map = {WayFormat.W_ED2K: "电驴(ed2k)"}


class Episode:
    def __init__(self, video: dict):
        self.video = video

    def get_name(self):
        return self.video.get("name", "")

    def get_episode_no(self):
        return int(self.video.get("episode", ""))

    def get_date(self):
        ts = int(self.video.get("dateline", 0))
        if ts == 0:
            return None

        return time.strftime("%Y-%m-%d %H:%M", time.localtime(ts))

    def get_size(self):
        return self.video.get("size", "?MB")

    def get_latest_episode_no(self):
        return int(max([v for v in self.video], key=lambda v: v.get_episode_no()))

    def get_support_ways(self):
        raw_ways = self.video.get("files", None)
        if len(raw_ways) == 0:
            return []

        std_ways = []
        for w in raw_ways:
            try:
                std_ways.append(WayFormat(w.get("way", "")))
            except ValueError as e:
                print("warning: unsupport download way", e)

        return std_ways

    def get_url(self, way: WayFormat) -> (str, str, str):
        files = self.video.get("files", None)
        if files is None:
            return None

        res = []
        if way == WayFormat.W_IDONTCARE:
            res = [f for f in files]
        else:
            res = [f for f in filter(lambda x: x.get("way", "") == way.value, files)]

        if len(res) <= 0:
            return None

        final = res[0]
        return (
            final.get("way_cn", ""),
            final.get("passwd", ""),
            final.get("address", ""),
        )


class Season:
    def __init__(self, season: dict):
        self.season = season
        self.format_blacklist_filter = lambda x: x not in [
            VideoFormat.V_APP,
            VideoFormat.V_HDTV,
            VideoFormat.V_HR_HDTV,
            VideoFormat.V_DVD,
            VideoFormat.V_DVDSCR,
        ]

    def get_num(self):
        return int(self.season.get("season_num", 0))

    def get_name(self):
        return self.season.get("season_cn", "")

    def get_support_format(self):
        raw_formats = self.season.get("formats", [])
        if len(raw_formats) == 0:
            return []

        std_formats = []
        for f in raw_formats:
            try:
                std_formats.append(VideoFormat(f))
            except ValueError as e:
                print("Unsupport VideoFormat", f, e)

        return list(filter(self.format_blacklist_filter, std_formats))

    def get_support_way(self):
        episodes = self.get_episodes(VideoFormat.V_IDONTCARE)
        ways = set()
        for e in episodes:
            ways.update(e.get_support_ways())

        return list(ways)

    def get_episodes(self, video_format: VideoFormat):
        items = self.season.get("items", None)
        if items is None:
            return None

        videos = []

        if video_format == VideoFormat.V_IDONTCARE:
            first_key = list(items.keys())[0]
            videos = items.get(first_key, None)
        else:
            videos = items.get(video_format.value, None)

        if videos is None:
            return None

        episodes = [Episode(e) for e in videos]
        episodes.reverse()
        return episodes


class YYETS:
    def __init__(self, filename: str):
        with open(filename, "r") as f:
            video_source = json.load(f)
            if video_source.get("info", "") != "OK":
                raise Exception("资源文件解析异常")
            data = video_source.get("data", None)
            if data is None:
                raise Exception("没有解析到资源数据")
            self.info = data.get("info", None)
            if self.info is None:
                raise Exception("没有解析到视频元数据")
            self.videolist = data.get("list", None)
            if self.info is None:
                raise Exception("没有解析到下来列表")

            self.season_list = [Season(x) for x in self.videolist]
            self.season_list.reverse()

    def get_resource_info(self):
        return self.info

    def get_all_season_no(self):
        return [x.get_num() for x in self.season_list]

    def get_total(self) -> (int, int):
        seanson_count = len(self.season_list)
        episode_count = 0
        for s in self.season_list:
            episode_count += len(s.get_episodes(VideoFormat.V_IDONTCARE))

        return (seanson_count, episode_count)

    def get_latest_season_no(self) -> int:
        return max([x for x in self.season_list], key=lambda x: int(x.get_num()))

    def get_all_support_formats(self):
        unique_formats = set()
        for season in self.season_list:
            unique_formats.update(season.get_support_format())

        return unique_formats

    def get_all_support_ways(self):
        unique_ways = set()
        for season in self.season_list:
            unique_ways.update(season.get_support_way())

        return unique_ways

    def get_all_episodes(self, season_no: int, video_format: VideoFormat):
        ss = [s for s in self.season_list if season_no == s.get_num()]
        if len(ss) == 0:
            return None

        return ss[0].get_episodes(video_format)

    def get_one_episode(
        self, video_format: VideoFormat, season_no: int, episode_no: int
    ):
        ss = [s for s in self.season_list if season_no == s.get_num()]
        if len(ss) == 0:
            return None

        es = [
            e
            for e in ss[0].get_episodes(video_format)
            if e.get_episode_no() == episode_no
        ]
        if len(es) == 0:
            return None

        return es[0]